import { Button, Table, Typography } from 'antd';
import React, { useEffect, useImperativeHandle, useState } from 'react';
import EditableRow from '@/component/param-setting/editable-row';
import EditableCell from '@/component/param-setting/editable-cell';
import { ParamType } from '@/component/param-setting/enum';
import WSetting from '@/component/param-setting/widgets/w-setting';

export interface Item {
  key?: string;
  paramCode: string;
  paramDesc: string;
  paramType: string;
  valueType: string;
  value?: any;
  dataValueOptions?: any[];
  objectAttr: Item[];
  optional?: boolean;
  editing?: boolean;
}

const ParamSetting = React.forwardRef<any, any>((props: any, ref: any) => {
  const {
    dataSource = [],
    hideAdd,
    onChange,
    onFormChange,
    hasOptional,
    ...resProps
  } = props;
  const [data, setData] = useState<Item[]>([]);
  const [formObj, setFormObj] = useState<any>({});
  const [expandKey, setExpandKey] = useState<string[]>([]);

  useEffect(() => {
    const dataCopy = JSON.parse(JSON.stringify(dataSource));
    dataCopy.forEach((item: Item, index: number) => {
      item.objectAttr.forEach((item, idx) => {
        if (!item.key) {
          item.key = `${index}-${idx}`;
        }
      });
      if (!item.key) {
        item.key = `${index}`;
      }
    });
    const keys = dataCopy
      .filter((item: any) => item.objectAttr.length > 0)
      .map((item: any) => item.key);
    setExpandKey(keys);
    setData(dataCopy);
  }, [dataSource]);

  useImperativeHandle(ref, () => ({
    getValue: () => {
      const values = JSON.parse(JSON.stringify(data));
      values.forEach((item: any) => {
        item.objectAttr = item.objectAttr.map((item: any) => {
          const value = formObj[item.key]?.getFieldValue?.() || item;
          delete value.key;
          delete value.editing;
          return value;
        });
        delete item.key;
        delete item.editing;
      });
      return values;
    },
    validate: () => {
      return Promise.all(
        Object.values(formObj).map((item: any) => item.validateFields()),
      );
    },
    getErrors: () => {
      return Promise.all(
        Object.values(formObj).map((item: any) => item.getFieldsError()),
      );
    },
  }));

  const isEditing = (record: Item) => record.editing;

  const edit = (record: Item) => {
    record.editing = true;
    setData([...data]);
    onChange?.(data);
  };

  function del(record: Item) {
    const index = data.findIndex((item) => item.key === record.key);
    data.splice(index, 1);
    setData([...data]);
    onChange?.(data);
  }

  function save(key: React.Key) {
    const form = formObj[key];
    const row = form.getFieldValue() as Item;
    const newData = [...data];
    const index = newData.findIndex((item) => key === item.key);
    const item = newData[index];
    row.objectAttr = item.objectAttr;
    newData.splice(index, 1, {
      ...item,
      ...row,
      editing: true,
    });
    setData(newData);
  }

  function saveDataValueOptions(record: any, dataValueOptions: any) {
    const key = record.key;
    const form = formObj[key];
    const row = form.getFieldValue() as Item;
    const newData = [...data];
    const index = newData.findIndex((item) => key === item.key);
    const item = newData[index];
    row.dataValueOptions = dataValueOptions;
    row.value = dataValueOptions
      ?.filter((item: any) => item.isDefault)
      .map((item: any) => item.code)
      ?.join(',');
    newData.splice(index, 1, {
      ...item,
      ...row,
    });
    setData(newData);
  }

  async function addProperty(key: React.Key) {
    const index = data.findIndex((item) => key === item.key)!;
    const item = data[index];
    item.objectAttr.push({
      key: `${index}-${item.objectAttr.length}`,
      paramCode: '',
      paramDesc: '',
      paramType: '',
      valueType: '',
      value: '',
      dataValueOptions: [],
      objectAttr: [],
      optional: true,
    });
    setData([...data]);
    setExpandKey([...expandKey, item.key!]);
  }

  const columns = [
    {
      title: '名称',
      dataIndex: 'paramCode',
      editable: true,
      width: 150,
    },
    {
      title: '描述',
      dataIndex: 'paramDesc',
      editable: true,
    },
    {
      title: '类型',
      dataIndex: 'paramType',
      editable: true,
      width: 180,
    },
    {
      title: '值类型',
      dataIndex: 'valueType',
      editable: true,
      width: 150,
    },
    {
      title: '可选',
      dataIndex: 'optional',
      editable: true,
      width: 100,
    },
    {
      title: '值',
      dataIndex: 'value',
      editable: true,
      width: 150,
    },
    // {
    //   title: '值',
    //   dataIndex: 'dataValueOptions',
    //   editable: true,
    //   width: 150,
    // },
    {
      title: '操作',
      width: 200,
      dataIndex: 'operation',
      render: (_: any, record: Item) => {
        const editable = record.editing;
        return (
          <span>
            {hasOptional && record.paramType !== ParamType.对象 && (
              <Typography.Link style={{ marginRight: 8 }}>
                <WSetting
                  value={record.dataValueOptions}
                  onChange={(dataValueOptions: any) =>
                    saveDataValueOptions(record, dataValueOptions)
                  }
                />
              </Typography.Link>
            )}
            {record.paramType === ParamType.对象 ? (
              <Typography.Link
                onClick={() => addProperty(record.key!)}
                style={{ marginRight: 8 }}
              >
                添加属性
              </Typography.Link>
            ) : null}
            {!editable && (
              <Typography.Link
                onClick={() => edit(record)}
                style={{ marginRight: 8 }}
              >
                编辑
              </Typography.Link>
            )}
            <Typography.Link onClick={() => del(record)}>删除</Typography.Link>
          </span>
        );
      },
    },
  ];
  const mergedColumns = columns
    // .filter((item) => hasOptional && item.dataIndex !== 'value' || (!hasOptional && item.dataIndex !== 'dataValueOptions'))
    .filter((item) => item.dataIndex !== 'optional' || hasOptional)
    .map((col) => {
      if (!col.editable) {
        return col;
      }
      return {
        ...col,
        onCell: (record: Item) => ({
          record,
          inputType: 'text',
          dataIndex: col.dataIndex,
          title: col.title,
          editing: isEditing(record),
          onSaveValue: () => save(record.key!),
          hidden: hideAdd,
          hasOptional: hasOptional,
        }),
      };
    });

  function handleChange(children: Item[], record: Item) {
    record.objectAttr = children;
    setData([...data]);
  }

  const expandedRowRender = (record: Item) => {
    if (record.objectAttr && record.objectAttr.length > 0) {
      const props = {
        expandable: null,
        rowExpandable: false,
        showHeader: false,
        dataList: record.objectAttr,
      };
      const data = record.objectAttr.slice(0);
      return (
        <ParamSetting
          dataSource={data}
          hideAdd={true}
          onChange={(list: Item[]) => handleChange(list, record)}
          onFormChange={onSaveForm}
          hasOptional={hasOptional}
          {...props}
        />
      );
    }
    return <></>;
  };

  function onSaveForm(key: any, form: any) {
    formObj[key] = form;
    onFormChange?.(key, form);
    setFormObj({ ...formObj });
  }

  function onRow(record: Item) {
    return {
      onSaveForm,
      record,
    };
  }

  const handleAdd = () => {
    const newData: Item = {
      key: data.length.toString(),
      paramCode: '',
      paramDesc: '',
      paramType: '',
      valueType: '',
      value: '',
      dataValueOptions: [],
      objectAttr: [],
      editing: true,
    };
    if (hasOptional) {
      newData.optional = true;
    }
    setData([...data, newData]);
  };

  function handleExpandChange(expandedRows: any[]) {
    setExpandKey(expandedRows);
  }

  return (
    <>
      {!hideAdd && (
        <div style={{ textAlign: 'right' }}>
          <Button
            onClick={handleAdd}
            type="primary"
            style={{ marginBottom: 16 }}
          >
            添加参数
          </Button>
        </div>
      )}
      <Table
        style={{ paddingLeft: hideAdd ? 20 : 0 }}
        components={{
          body: {
            cell: EditableCell,
            row: EditableRow,
          },
        }}
        onRow={onRow}
        bordered
        dataSource={data}
        columns={mergedColumns}
        rowClassName="editable-row"
        expandable={{
          expandedRowRender,
          expandedRowKeys: expandKey,
          onExpandedRowsChange: handleExpandChange,
        }}
        rowExpandable={(record: Item) =>
          record.paramType === ParamType.对象 &&
          record.objectAttr &&
          record.objectAttr.length > 0
        }
        pagination={{
          pageSize: 100,
          hideOnSinglePage: true,
        }}
        {...resProps}
      />
    </>
  );
});

export default ParamSetting;
